$OpenBSD: patch-lib_pgp_helper_pgpMem_c,v 1.2 2012/08/19 22:30:37 ajacoutot Exp $

From Julian Coleman <J.D.Coleman@newcastle.ac.uk> posted to
netbsd-bugs@netbsd.org:

The memory alignment strategy for PGP 5.0i causes bus errors on NetBSD/Sparc
because 8 byte variables are not aligned on an 8 byte boundary.

In src/lib/pgp/helper/pgpMem.c:PGP_INTERNAL_ALLOC(), a header is added to
all malloc()'ed memory and the pointer returned is incremented by the size
of the header.  However, there are no constraints to see if this increment
is correctly aligned.

The problem might also occur on other OS's running on the Sparc.  A patch
is appended (based on one used for the Chimera web browser).

J

PS.  The exact problem is that 'off_t' is an 8 byte value, but the header
length is only a mulitple of 4.  Pgpe crashes at pgpFileMod.c:333, when it
tries to modify 'context->filesize'.

PPS.  Maybe 'long long' should also be in the union (e.g. for Solaris 2).

--- lib/pgp/helper/pgpMem.c.orig	Sun Aug 10 21:05:32 1997
+++ lib/pgp/helper/pgpMem.c	Tue Apr 23 03:06:29 2002
@@ -19,6 +19,20 @@
 #include "pgpDebug.h"
 #include "pgpLeaks.h"
 
+/*
+ * Make sure any memory chunks are correctly aligned.
+ * This can be forced by defining ALIGNSIZE (in bytes).
+ */
+#ifndef ALIGNSIZE
+typedef struct Alignment
+{
+  union { int a; char *b; size_t c; off_t d; long e; } Align;
+} Alignment;
+#define MEMALIGN(x) ((x / sizeof(Alignment) + 1) * sizeof(Alignment))
+#else
+#define MEMALIGN(x) ((x / ALIGNSIZE + 1) * ALIGNSIZE)
+#endif
+
 /* Fills allocated/deallocated memory with 0xDD's */
 #ifndef DEBUG_FILL_MEM
 #define DEBUG_FILL_MEM			DEBUG
@@ -69,11 +83,11 @@ struct MemHeader
 };
 
 #define UserPtrToMemHeader(userPtr)		\
-		((MemHeader *)((char *)(userPtr) - sizeof(MemHeader)))
+		((MemHeader *)((char *)(userPtr) - MEMALIGN(sizeof(MemHeader))))
 #define MemHeaderToUserPtr(hdrPtr)		\
- 	((void *)((char *)(hdrPtr) + sizeof(MemHeader)))
+ 	((void *)((char *)(hdrPtr) + MEMALIGN(sizeof(MemHeader))))
 #define FullBlockSize(userSize)			\
-		(sizeof(MemHeader) + (userSize) + DEBUG_MEM_TAIL_MAGIC)
+		(MEMALIGN(sizeof(MemHeader)) + (userSize) + DEBUG_MEM_TAIL_MAGIC)
 
 /*
 * Defines the sequence of tail magic bytes. We want every byte to be
@@ -269,7 +283,7 @@ pgpMemSetTailMagic(
 	MemHeader *	header)
 {
 #if DEBUG_MEM_TAIL_MAGIC
-	char *		tailMagic = (char *)header + sizeof(MemHeader) + header->size;
+	char *		tailMagic = (char *)header + MEMALIGN(sizeof(MemHeader)) + header->size;
 	int			i;
 	
 	for (i = 0; i < DEBUG_MEM_TAIL_MAGIC; i++)
@@ -287,8 +301,9 @@ PGP_INTERNAL_ALLOC(
 	MemHeader *		header;
 	void *			userPtr;
 	
+	size += (MEMALIGN(sizeof(MemHeader)) - (sizeof(MemHeader)));
 	header = (MemHeader *)pgpPlatformAlloc(FullBlockSize(size));
-if (header == NULL)
+	if (header == NULL)
 		return NULL;
 
 	MaybeFillMem(header, FullBlockSize(size));
@@ -352,7 +367,7 @@ pgpRealloc(
 		if (newHeader == NULL)
 			return PGPERR_NOMEM;
 		pgpCopyMemory((void *)oldHeader, (void *)newHeader,
-					sizeof(MemHeader) + oldSize);
+					MEMALIGN(sizeof(MemHeader)) + oldSize);
 		MaybeFillMem(oldHeader, FullBlockSize(oldSize));
 		pgpPlatformFree(oldHeader);
 	}
